<template>
  <div class="fm-generate-form">
    <el-form
      ref="formRef"
      :model="formModel"
      :rules="formRules"
      :label-width="formConfig.labelWidth"
      :label-position="formConfig.labelPosition"
      :size="formConfig.size"
    >
      <template v-for="(element, index) in formList" :key="element.key || index">
        <generate-form-item :element="element" :form-model="formModel" />
      </template>
    </el-form>
  </div>
</template>

<script setup>
import { ref, reactive, computed, watch } from 'vue'
import GenerateFormItem from './GenerateFormItem.vue'

const props = defineProps({
  data: {
    type: Object,
    required: true
  },
  value: {
    type: Object,
    default: () => ({})
  }
})

const emit = defineEmits(['update:value'])

const formRef = ref(null)
const formModel = reactive({})
const formList = computed(() => props.data.list || [])
const formConfig = computed(() => props.data.config || { labelWidth: '100px', labelPosition: 'right', size: 'default' })

const formRules = computed(() => {
  const rules = {}
  formList.value.forEach(element => {
    if (element.type !== 'grid' && element.options.required) {
      rules[element.model] = [
        { required: true, message: `${element.label}不能为空`, trigger: 'blur' }
      ]
    }
    if (element.type === 'grid' && element.columns) {
      element.columns.forEach(col => {
        col.list.forEach(item => {
          if (item.options.required) {
            rules[item.model] = [
              { required: true, message: `${item.label}不能为空`, trigger: 'blur' }
            ]
          }
        })
      })
    }
  })
  return rules
})

const initFormModel = () => {
  formList.value.forEach(element => {
    if (element.type !== 'grid') {
      const value = props.value[element.model]
      if (value !== undefined) {
        formModel[element.model] = value
      } else if (element.options.defaultValue !== undefined && element.options.defaultValue !== null) {
        formModel[element.model] = element.options.defaultValue
      } else {
        if (element.type === 'checkbox' || (element.type === 'select' && element.options.multiple)) {
          formModel[element.model] = []
        } else if (element.type === 'switch') {
          formModel[element.model] = false
        } else if (element.type === 'number' || element.type === 'rate' || element.type === 'slider') {
          formModel[element.model] = 0
        } else {
          formModel[element.model] = ''
        }
      }
    } else if (element.columns) {
      element.columns.forEach(col => {
        col.list.forEach(item => {
          const value = props.value[item.model]
          if (value !== undefined) {
            formModel[item.model] = value
          } else if (item.options.defaultValue !== undefined && item.options.defaultValue !== null) {
            formModel[item.model] = item.options.defaultValue
          } else {
            if (item.type === 'checkbox' || (item.type === 'select' && item.options.multiple)) {
              formModel[item.model] = []
            } else if (item.type === 'switch') {
              formModel[item.model] = false
            } else if (item.type === 'number' || item.type === 'rate' || item.type === 'slider') {
              formModel[item.model] = 0
            } else {
              formModel[item.model] = ''
            }
          }
        })
      })
    }
  })
}

watch(() => props.data, () => {
  initFormModel()
}, { immediate: true, deep: true })

watch(formModel, () => {
  emit('update:value', formModel)
}, { deep: true })

const getData = () => {
  return new Promise((resolve, reject) => {
    formRef.value.validate((valid) => {
      if (valid) {
        resolve(formModel)
      } else {
        reject(new Error('表单验证失败'))
      }
    })
  })
}

const reset = () => {
  formRef.value.resetFields()
}

defineExpose({
  getData,
  reset
})
</script>

<style lang="scss" scoped>
.fm-generate-form {
  width: 100%;
}
</style>